<?php
namespace app\index\controller;
use think\Controller;
use think\Db;
header("Content-Type: text/html; charset=utf-8");
/**
* 
*/
class FileOperating extends controller
{
    /*
    *功能：移动文件
    *传入三个参数：
    *$dir表示被移动的文件的绝对路径
    *$dirTo表示移动的目的地点的绝对路径
    *$isDel表示是否删除原来的文件，true代表删除，false代表保留
    */
    function toCopy($dir,$dirTo,$isDel=false){
        $dir = $this->cnToGBK($dir);
        if(file_exists($dir)){
            //如果有“/”字符，则转为“\”
            while (strstr($dirTo, "/") != false) {
                $dirTo = str_replace("/", "\\", $dirTo);
            }

            // 如果不存在该路劲，则创建相应目录
            $arr = explode("\\", $dirTo);
            $a = iconv("UTF-8", "GBK", $arr[0]);
            // 不兼容中文
            for ($i=1; $i < count($arr); $i++) { 
                if(!file_exists($a)){
                    mkdir($a);//只能创建已有目录下的一目录
                }
                $a .= "\\" . iconv("UTF-8", "GBK", $arr[$i]);
            }
            // 使用重命名回复中文路径
            $arr2 = explode("\\", $a);
            $a = $arr2[0];
            $a1 = $arr[0];
            for ($i=1; $i < count($arr2); $i++) { 
                $a .= "\\" . $arr2[$i];
                $a1 .= "\\" . $arr[$i];
                if(strchr($a,$a1) == -1){
                    rename($a, $a1);
                }
            }
            
            // 移动文件
            copy($dir, iconv("UTF-8", "GBK", $dirTo));
            // 根据需求删除原有文件
            if($isDel){
                unlink($dir);
            }

            return true;
        }else{
            return false;
        }
    }

    /*
    *功能：获取文件夹里的所有文件
    *$pathName  必需，指定读取的目录文件夹
    *$isArr   可选，true则返回一维数组，false则返回多维数组 
    *默认返回以目录结构为框架的多维数组，
    */
    function recurDir($pathName,$isArr = false){
        //将结果保存在result变量中
        $result = array();
        $temp = array();
        $pathName = iconv("utf-8","gbk",$pathName);
        //判断传入的变量是否是目录
        if(!is_dir($pathName) || !is_readable($pathName)) {
            return null;
        }
        
        //取出目录中的文件和子目录名,使用scandir函数
        $allFiles =scandir($pathName);
        //遍历他们
        foreach($allFiles as $fileName) {
            //判断是否是.和..
            if(in_array($fileName, array('.', '..'))) {
                continue;
            }
            //路径加文件名
            $fullName = $pathName.'/'.$fileName;
            //如果是目录的话就继续遍历这个目录
            if(is_dir($fullName)) {
               //将这个目录中的文件信息存入到数组中
                $result[iconv('gbk' , 'utf-8' , $fullName)] = recurDir($fullName); 
            }else {
                //如果是文件就先存入临时变量
                $temp[] = iconv('gbk' , 'utf-8' ,$fullName);
            }
        }
        //取出文件
        if($temp) {
            foreach($temp as $f) {
                $f = str_replace('/', '\\', $f);
                $result[] = $f;
            }
        }
        //根据需求转为一维数组
        if($isArr){
            $result = $this->reduceArray($result);
         }

        return $result;
    }

    /*
    * 功能：将多维数组转成一维数组
    * $array：必需,需要转换的多维数组
    * 返回值：成功则返回转换后的数组，否则返回false；
    */
    function reduceArray($array) {
        if(!is_array($array)){
            return false;
        }

        $return = [];
        array_walk_recursive($array, function ($x) use (&$return) {
            $return[] = $x;
        });
        return $return;
    }

    /*
    * 功能：如果路径有中文则转为GBK，如果没有则不转换
    * $path：必需,需要识别并转换的值
    */
    function cnToGBK($path='')
    {
        // 如果要下载的文件文件名路径包含中文，自动转为gbk
        if(preg_match('/[\x{4e00}-\x{9fa5}]/u', $path)>0) {
            $path = iconv("UTF-8", "gbk", $path);
        }

        return $path;
    }

    /*
    * 功能：将文件压缩打包
    * $fileNameArr: 必需, 需要压缩的文件，以一维数组形式存储绝对路劲
    * $zipName:     可选，压缩后的文件名，默认为下载时的当前时间命名，格式为：“YmdHis”
    * $dir:         可选，压缩后的文件路径，默认为第一个被压缩的文件的路径
    * $isSaveDir    可选，是否保留目录结构
    * $delDir       可选，要去除的目录路径
    * 返回值：返回压缩后的文件的绝对路径
    */
    function toZip($fileNameArr,$zipName = "",$dir = "",$isSaveDir = false, $delDir = "")
    {
        if($zipName == ""){
            if($dir == ""){
                $dir = dirname($this->cnToGBK($fileNameArr[0]));
            }
            $date = date("YmdHis");
            $zipName = $dir . DS . $date . ".zip";
        }

        $zip = new \ZipArchive;
        if($zip->open($zipName,\ZIPARCHIVE::OVERWRITE | \ZIPARCHIVE::CREATE) !== true){
            exit("无法打开文件，或者文件创建失败");
        }
        $date = date("YmdHis");
        foreach ($fileNameArr as $fileName) {
            $fileName = iconv("UTF-8", "gbk", $fileName);
            
            if(file_exists($fileName)){
                copy($fileName, dirname($fileName) . DS . $date . ".txt");
                $zip->addFile(dirname($fileName) . DS . $date . ".txt","tmp");

                if($isSaveDir){
                    $tmp = str_replace($delDir, "", $fileName);
                }else{
                    $tmp = basename($fileName);
                }
                $zip->renameName("tmp",$tmp);
            }
        }

        $zip->close();
        unlink(dirname($fileName) . DS . $date . ".txt");
        unlink(dirname($zipName) . DS . $date . ".txt");
        return $zipName;
    }

    /*
    * 功能：下载单个文件
    * $filename:    必需, 要下载的文件，绝对路径
    * $zipName:     可选，压缩后的文件名，默认为下载时的当前时间命名，格式为：“YmdHis”
    * $dir:         可选，压缩后的文件路径，默认为第一个被压缩的文件的路径
    * $isSaveDir    可选，是否保留目录结构
    * $delDir       可选，要去除的目录路径
    * 返回值：返回压缩后的文件的绝对路径
    */
    function download($filename, $downName=""){

        if(file_exists($filename)){
            // 如果没有规定下载名字，则以被下载的文件名命名
            if($downName == ""){
                $downName = basename($filename);
            }

            // 如果要下载的文件文件名路径包含中文，自动转为gbk
            $filename = $this->cnToGBK($filename);

            // 下载文件
            $file = fopen($filename,"r");
            header('Cache-control: private');// 发送 headers 
            // Header("Content-type: application/force-download");//强制下载
            header("Content-Type: application/octet-stream"); //返回的是文件的形式
            header("Content-Transfer-Encoding: binary"); // 告诉浏览器，这是二进制文件
            header("Content-Length:".filesize($filename)); // 告诉浏览器，文件大小
            header('Content-Disposition: attachment;filename="'.$downName); //attachment表明不在页面输出打开，直接下载
            header("Accept-Ranges:bytes"); //下载的速度的单位
            header("Pragma: no-cache"); //不缓存页面
            flush();// flush 内容输出到浏览器端 
            ob_clean();
            echo fread($file, filesize($filename));
            fclose($file);
            flush();
        }else{
            exit("文件不存在");
        }
    }

}

?>